home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Utilities / Graphic / Conversion / viewers / GL Viewer 1.1.1 / glib ƒ / glib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-06  |  12.5 KB  |  602 lines  |  [TEXT/KAHL]

  1. #if 0
  2. #ident "@(#)glib.c    1.5 91/04/01 XGRASP"
  3. #endif
  4. /*-
  5.  * glib.c - GRASP graphics librarian.
  6.  *
  7.  * Copyright (c) 1991 by Patrick J. Naughton
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and that
  12.  * both that copyright notice and this permission notice appear in
  13.  * supporting documentation.
  14.  *
  15.  * This file is provided AS IS with no warranties of any kind.  The author
  16.  * shall have no liability with respect to the infringement of copyrights,
  17.  * trade secrets or any patents by this file or any part thereof.  In no
  18.  * event will the author be liable for any lost revenue or profits or
  19.  * other special, indirect and consequential damages.
  20.  *
  21.  * Comments and additions should be sent to the author:
  22.  *
  23.  *                     Patrick J. Naughton
  24.  *                     Sun Microsystems
  25.  *                     2550 Garcia Ave, MS 10-20
  26.  *                     Mountain View, CA 94043
  27.  *                     (415) 336-1080
  28.  *
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <assert.h>
  34. #include <string.h>
  35. #include <sys/types.h>
  36. #include <console.h>
  37. #include "match.h"
  38.  
  39.  
  40. char       *pname;
  41. extern char *strrchr();
  42.  
  43.  
  44. #define TOO_MANY_ENTRIES    256
  45.  
  46.  
  47. typedef struct {
  48.     char        fname[14];
  49.     long        offset;
  50.     long        len;
  51.     char       *data;
  52. }           FilenameStruct;
  53.  
  54.  
  55. typedef struct
  56. {
  57.     short    fileIndex;
  58.  
  59.     char    fIsPattern;
  60.     char    fIsGoodPattern;
  61.     short    numMatched;
  62.     short      *pMatchedIndices;
  63.     
  64. }        MatchStruct, *MatchPtr;
  65.  
  66.  
  67.     static void
  68. error(s1, s2, s3)
  69.     char       *s1, *s2, *s3;
  70. {
  71.     fprintf(stderr, s1, pname, s2, s3);
  72.     console_options.pause_atexit = 1;
  73.     exit(1);
  74. }
  75.  
  76.  
  77.     static u_short
  78. GetWord(fp)
  79.     FILE       *fp;
  80. {
  81.     u_short      b1 = (u_char) getc(fp);
  82.     u_short      b2 = (u_char) getc(fp);
  83.  
  84.     return (u_short) (b1 + b2 * 256);
  85. }
  86.  
  87.     static u_long
  88. GetLong(fp)
  89.     FILE       *fp;
  90. {
  91.     u_long      b1 = (u_char) getc(fp);
  92.     u_long      b2 = (u_char) getc(fp);
  93.     u_long      b3 = (u_char) getc(fp);
  94.     u_long      b4 = (u_char) getc(fp);
  95.     u_long        retVal = b1 + (b2 + (b3 + b4 * 256L) * 256L) * 256L;
  96.  
  97.  
  98.     return retVal;
  99. }
  100.  
  101.  
  102.     static void
  103. PutWord(fp, w)
  104.     FILE       *fp;
  105.     unsigned int w;
  106. {
  107.     unsigned char b1 = w & 255;
  108.     unsigned char b2 = (w >> 8) & 255;
  109.     putc(b1, fp);
  110.     putc(b2, fp);
  111. }
  112.  
  113.  
  114.     static void
  115. PutLong(fp, l)
  116.     FILE       *fp;
  117.     unsigned long l;
  118. {
  119.     unsigned char b1 = l & 255;
  120.     unsigned char b2 = (l >> 8) & 255;
  121.     unsigned char b3 = (l >> 16) & 255;
  122.     unsigned char b4 = (l >> 24) & 255;
  123.  
  124.     putc(b1, fp);
  125.     putc(b2, fp);
  126.     putc(b3, fp);
  127.     putc(b4, fp);
  128. }
  129.  
  130.  
  131.     static char *
  132. lowerstr (char *s)
  133.  
  134. {
  135.     char *retVal = s;
  136.  
  137.     while (*s)
  138.     {
  139.     if (*s >= 'A' && *s <= 'Z')
  140.         *s = *s + 'a' - 'A';
  141.     s++;
  142.     }
  143.  
  144.     return retVal;
  145. }
  146.  
  147.  
  148.     static void
  149. extractfile(in, dir, i)
  150.     FILE       *in;
  151.     FilenameStruct *dir;
  152.     int         i;
  153. {
  154.     long        len;
  155.     char       *data;
  156.     FILE       *out;
  157.  
  158.     fseek(in, dir[i].offset, 0);
  159.     len = GetLong(in);
  160.     len &= 0x00ffffff;
  161.     data = (char *) malloc(len);
  162.     if (!data)
  163.     error("%s: not enough memory\n", NULL, NULL);
  164.     fread(data, len, 1, in);
  165.     out = fopen(dir[i].fname, "wb");
  166.     if (!out)
  167.     error("%s: error writing: %s\n", dir[i].fname, NULL);
  168.     fwrite(data, len, 1, out);
  169.     fclose(out);
  170.     free(data);
  171. }
  172.  
  173.  
  174.     static void
  175. writefile(fname, dir, nfiles)
  176.     char       *fname;
  177.     FilenameStruct *dir;
  178.     int         nfiles;
  179. {
  180.     FILE       *out;
  181.     int         i;
  182.     long        offset = 2 + (nfiles + 1) * (13 + 4);
  183.  
  184.     out = fopen(fname, "wb");
  185.     PutWord(out, (nfiles + 1) * (13 + 4));
  186.     for (i = 0; i < nfiles; i++) {
  187.     PutLong(out, offset);
  188.     offset += dir[i].len + 4;
  189.     fwrite(dir[i].fname, 13, 1, out);
  190.     }
  191.     PutLong(out, 0);
  192.     fwrite("             ", 13, 1, out);
  193.     for (i = 0; i < nfiles; i++) {
  194.     PutLong(out, dir[i].len);
  195.     fwrite(dir[i].data, dir[i].len, 1, out);
  196.     }
  197.     fclose(out);
  198. }
  199.  
  200.  
  201.     static int
  202. findname(dir, nfiles, s)
  203.     FilenameStruct *dir;
  204.     int         nfiles;
  205.     char       *s;
  206. {
  207.     int         i;
  208.  
  209.     if (dir)
  210.     for (i = 0; i < nfiles; i++)
  211.         if (!strcmp(dir[i].fname, s))
  212.         return i;
  213.     return -1;
  214. }
  215.  
  216.  
  217.     static 
  218. usage()
  219. {
  220.     error("usage: %s [-dstuea] libname [files...]\n", NULL, NULL);
  221. }
  222.  
  223.  
  224. main(argc, argv)
  225.     int         argc;
  226.     char       *argv[];
  227. {
  228.     int         i;
  229.     FILE       *in;
  230.     FILE       *out;
  231.     char       *libfname;
  232.     char       *opfname;
  233.     long        nfiles = 0;
  234.     FilenameStruct *dir = 0;
  235.     int         thefile = -1;
  236.     short    numSpecFiles = 0;
  237.     short    numFound = 0;
  238.     MatchStruct *pFileIndices;
  239.     int         c;
  240.     int         dflg = 0;
  241.     int         sflg = 0;
  242.     int         tflg = 0;
  243.     int         uflg = 0;
  244.     int         eflg = 0;
  245.     int         aflg = 0;
  246.  
  247.     extern char *optarg;
  248.     extern int  optind;
  249.     extern int    mwf_ccommand (char ***av);
  250.  
  251.  
  252.     argc = mwf_ccommand (&argv);
  253.  
  254.     pname = argv[0];
  255.  
  256.     if (argc == 1)
  257.     usage();
  258.     while ((c = egetopt(argc, argv, "hd:s:t:u:e:a:")) != -1)
  259.     switch (c) {
  260.     case 'h':
  261.         printf("\nusage: glib [-dstuea] libname [files...]\n");
  262.         printf("\n        where the following commands are supported:\n\n");
  263.         printf("\t-d   delete file from library\n");
  264.         printf("\t-s   extended file list\n");
  265.         printf("\t-t   quick file list\n");
  266.         printf("\t-u   update (add) file to library\n");
  267.         printf("\t-e   extract file from library\n");
  268.         printf("\t-a   extract all files from library\n\n");
  269.         exit(0);
  270.     case 'd':
  271.         if (uflg || eflg || aflg)
  272.         usage();
  273.         else
  274.         dflg++;
  275.         libfname = optarg;
  276.         break;
  277.     case 's':
  278.         if (tflg)
  279.         usage();
  280.         else
  281.         sflg++;
  282.         libfname = optarg;
  283.         break;
  284.     case 't':
  285.         if (sflg)
  286.         usage();
  287.         else
  288.         tflg++;
  289.         libfname = optarg;
  290.         break;
  291.     case 'u':
  292.         if (dflg || eflg || aflg)
  293.         usage();
  294.         else
  295.         uflg++;
  296.         libfname = optarg;
  297.         break;
  298.     case 'e':
  299.         if (dflg || uflg || aflg)
  300.         usage();
  301.         else
  302.         eflg++;
  303.         libfname = optarg;
  304.         break;
  305.     case 'a':
  306.         if (dflg || uflg || eflg)
  307.         usage();
  308.         else
  309.         aflg++;
  310.         libfname = optarg;
  311.         break;
  312.     default:
  313.         usage();
  314.     }
  315.  
  316.     if (!libfname)
  317.     usage();
  318.  
  319.     if ((dflg || uflg || eflg) && optind == argc)
  320.         error ("%s: [-deu] no files specified after library name\n",
  321.                (char *) NULL, (char *) NULL);
  322.  
  323.     /*...Build up a list of patterns to search for...*/
  324.  
  325.     if (dflg || eflg)
  326.     {
  327.         numSpecFiles = argc - optind;
  328.  
  329.         assert (
  330.         pFileIndices = (MatchPtr) calloc ((size_t) numSpecFiles,
  331.                           (size_t) sizeof (MatchStruct)));
  332.  
  333.  
  334.     for (i = 0; i < numSpecFiles; i++)
  335.     {
  336.         MatchPtr    pFileIndex = pFileIndices + i;
  337.         char       *pSearchFor = argv[optind + i];
  338.  
  339.  
  340.         pFileIndex->fileIndex = -1;
  341.  
  342.         /*...Accommodate regular expressions...*/
  343.  
  344.         if (pFileIndex->fIsPattern = is_pattern (lowerstr (pSearchFor)))
  345.         {
  346.         int    error_type;
  347.  
  348.  
  349.         pFileIndex->numMatched = 0;
  350.  
  351.         if (pFileIndex->fIsGoodPattern = is_valid_pattern (pSearchFor, &error_type))
  352.         {
  353.             /*...The following relies on malloc ((size_t) 0) returning a
  354.              *     legitimate value for subsequent realloc () calls.
  355.              */
  356.  
  357.             pFileIndex->pMatchedIndices = (short *) malloc ((size_t) 0);
  358.         }
  359.         }
  360.     }
  361.     }
  362.  
  363.     if (!sflg && !tflg)
  364.         console_options.pause_atexit = 0;
  365.  
  366.     in = fopen(libfname, "rb");
  367.     if (!in && !uflg)
  368.     error("%s: %s not found!\n", libfname, NULL);
  369.  
  370.     if (in /* != (FILE *) NULL */)
  371.     {
  372.     nfiles = (GetWord(in) / 17) - 1;
  373.     if (0 >= nfiles || nfiles > TOO_MANY_ENTRIES)
  374.         error ("%s: Not a GL archive (# entries = %ld)\n",
  375.                (char *) nfiles, (char *) NULL);
  376.  
  377.     dir = (FilenameStruct *) malloc(nfiles * sizeof(FilenameStruct));
  378.     for (i = 0; i < nfiles; i++)
  379.     {
  380.         dir[i].offset = GetLong(in);
  381.         fread(dir[i].fname, 13, 1, in);
  382.         dir[i].fname[13] = 0;
  383.         (void) lowerstr (dir[i].fname);
  384.  
  385.         if (numSpecFiles /* > 0 */)
  386.         {
  387.             short    j;
  388.  
  389.  
  390.         for (j = 0; j < numSpecFiles; j++)
  391.         {
  392.             MatchPtr pFileIndex = pFileIndices + j;
  393.  
  394.  
  395.             if (pFileIndex->fileIndex == -1)
  396.             {
  397.                 char   *pSearchFor = argv[optind + j];
  398.  
  399.  
  400.                 if (pFileIndex->fIsPattern && pFileIndex->fIsGoodPattern)
  401.                 {
  402.                     if (match (pSearchFor, dir[i].fname))
  403.                     {
  404.                         short    numMatched = pFileIndex->numMatched;
  405.  
  406.  
  407.                         assert (
  408.                         pFileIndex->pMatchedIndices =
  409.                             (short *) realloc (pFileIndex->pMatchedIndices,
  410.                                            (size_t) (numMatched + 1) *
  411.                                            sizeof (MatchStruct)));
  412.  
  413.                     pFileIndex->pMatchedIndices[numMatched] = i;
  414.  
  415.                 (pFileIndex->numMatched)++;
  416.  
  417.                  numFound++;
  418.  
  419.                 break;
  420.                     }
  421.                 }
  422.             else if (!strcmp (dir[i].fname, pSearchFor))
  423.             {
  424.                     pFileIndex->fileIndex = i;
  425.                     numFound++;
  426.                     break;
  427.             }
  428.             }
  429.         }
  430.         }
  431.     }
  432.  
  433.     if (numSpecFiles /* > 0 */ && numSpecFiles != numFound)
  434.     {
  435.         short j;
  436.  
  437.  
  438.         console_options.pause_atexit = 1;
  439.  
  440.         for (j = 0; j < numSpecFiles; j++)
  441.         {
  442.             MatchPtr    pFileIndex = pFileIndices + j;
  443.  
  444.  
  445.             if (pFileIndex->fileIndex == -1 &&
  446.                 (!pFileIndex->fIsPattern || pFileIndex->numMatched == 0))
  447.                 fprintf (stderr, "%s: %s not found in %s.\n",
  448.                          pname, argv[optind + j], libfname);
  449.         }
  450.  
  451.         if (numFound == 0)
  452.             error ("%s: None of the specified entries were found!\n",
  453.                    (char *) NULL, (char *) NULL);
  454.     }
  455.  
  456.     if (sflg || tflg || dflg || uflg) {
  457.         if (sflg)
  458.         printf("## filename.ext\toffset\tsize\n%s",
  459.                "-- ------------\t------\t----\n");
  460.         for (i = 0; i < nfiles; i++) {
  461.         fseek(in, dir[i].offset, 0);
  462.         dir[i].len = GetLong(in);
  463.         dir[i].len &= 0x00ffffff;
  464.         if (sflg)
  465.             printf("%2d %s\t%ld\t%ld\n",
  466.                i, dir[i].fname, dir[i].offset, dir[i].len);
  467.         else if (tflg)
  468.             printf("%s%c", dir[i].fname,
  469.                (i + 1) % 4 && i + 1 < nfiles ? '\t' : '\n');
  470.  
  471.         if (dflg || uflg) {
  472.             dir[i].data = (char *) malloc(dir[i].len);
  473.             if (!dir[i].data)
  474.             error("%s: not enough memory\n", NULL, NULL);
  475.             fread(dir[i].data, dir[i].len, 1, in);
  476.         }
  477.         }
  478.     }
  479.     }
  480.     if (eflg) {
  481.     for (i = 0; i < numSpecFiles; i++)
  482.     {
  483.         MatchPtr pFileIndex = pFileIndices + i;
  484.  
  485.  
  486.         if (pFileIndex->fileIndex != -1)
  487.         {
  488.         extractfile (in, dir, pFileIndex->fileIndex);
  489.         }
  490.         else if (pFileIndex->numMatched /* > 0 */)
  491.         {
  492.             short    j;
  493.  
  494.  
  495.             for (j = 0; j < pFileIndex->numMatched; j++)
  496.             extractfile (in, dir, pFileIndex->pMatchedIndices[j]);
  497.         }
  498.     }
  499.     fclose(in);
  500.     } else if (aflg) {
  501.     for (i = 0; i < nfiles; i++)
  502.         extractfile(in, dir, i);
  503.     fclose(in);
  504.     } else if (dflg) {
  505.     fclose(in);
  506.  
  507.     {
  508.         FilenameStruct *pNewDir = (FilenameStruct *)
  509.                           malloc (nfiles * sizeof (FilenameStruct));
  510.         short        ithFile = 0;
  511.  
  512.  
  513.         for (i = 0; i < nfiles; i++)
  514.         {
  515.             short    j;
  516.  
  517.  
  518.             /*...See if this entry is on the to-be-deleted list...*/
  519.  
  520.             for (j = 0; j < numSpecFiles; j++)
  521.             {
  522.                 MatchPtr pFileIndex = pFileIndices + j;
  523.  
  524.  
  525.                 if (pFileIndex->fileIndex == i)
  526.                 {
  527.                     goto next_i;
  528.                 }
  529.             else if (pFileIndex->numMatched /* > 0 */)
  530.             {
  531.                 short    j;
  532.     
  533.     
  534.                 for (j = 0; j < pFileIndex->numMatched; j++)
  535.                 {
  536.                 if (pFileIndex->pMatchedIndices[j] == i)
  537.                 goto next_i;
  538.                 }
  539.             }
  540.             }
  541.  
  542.             /*...Copy this entry...*/
  543.  
  544.         memcpy (&pNewDir[ithFile++], &dir[i], sizeof (FilenameStruct));
  545.  
  546.         next_i: ;
  547.         }
  548.  
  549.         nfiles = ithFile;
  550.         free ((char *) dir);
  551.         dir = pNewDir;
  552.     }
  553.  
  554.     writefile (libfname, dir, nfiles);
  555.     } else if (uflg) {
  556.  
  557.     if (in)
  558.         fclose(in);
  559.     for (i = optind; i < argc; i++) {
  560.         char       *s  = lowerstr (argv[i]);
  561.         char       *fn = strrchr(s, '/');
  562.         int         n;
  563.         int         idx;
  564.  
  565.         fn = (fn == 0) ? s : fn + 1;
  566.         n = strlen (fn);
  567.         if (n > 13)
  568.         error("%s: '%s' is too long, must be < 13 chars.\n", s, NULL);
  569.  
  570.         idx = findname (dir, nfiles, fn);
  571.  
  572.         if (idx == -1) {
  573.         nfiles++;
  574.         if (!dir)
  575.             dir = (FilenameStruct *) malloc(sizeof(FilenameStruct));
  576.         else
  577.             dir = (FilenameStruct *) realloc(dir,
  578.                          nfiles * sizeof(FilenameStruct));
  579.         idx = nfiles - 1;
  580.         } else
  581.         free(dir[idx].data);
  582.         memset(dir[idx].fname, 0, 14);
  583.         memcpy(dir[idx].fname, fn, n);
  584.         in = fopen(s, "rb");
  585.         if (!in)
  586.         error("%s: %s not found!\n", s, NULL);
  587.  
  588.         fseek(in, 0L, 2);    /* eof */
  589.         dir[idx].len = ftell(in);
  590.         fseek(in, 0L, 0);    /* bof */
  591.         dir[idx].data = (char *) malloc(dir[idx].len);
  592.         if (!dir[idx].data)
  593.         error("%s: not enough memory\n", NULL, NULL);
  594.         fread(dir[idx].data, dir[idx].len, 1, in);
  595.         fclose(in);
  596.     }
  597.     writefile(libfname, dir, nfiles);
  598.     }
  599.  
  600.     exit(0);
  601. }
  602.